﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;

using MSNPSharp;
using MSNPSharp.Core;
using MSNPSharp.DataTransfer;

namespace myServer
{
    public class ConversationHandle
    {
        private Conversation _conversation = null;
        private List<string> _leftusers = new List<string>(0);
        private List<TextMessage> _messagequene = new List<TextMessage>(0);
        private frmMain _clientform = null;
        private Dictionary<string, bool> _contactStatus = new Dictionary<string, bool>(0);
        //private bool _isChatForm = false;

        private Dictionary<string, CommandShell> _shells = new Dictionary<string, CommandShell>(0);

        public Conversation Conversation
        {
            get
            {
                return _conversation;
            }
        }

        public ConversationHandle(Conversation conversation, frmMain mainform, string account)
        {
            if (conversation != null)
            {
                _contactStatus.Add(account, false);
                _conversation = conversation;
                AddEvent();
            }
            else
            {
                //Create by local user
                _contactStatus.Add(account, true);
                _leftusers.Add(account);
            }
            _clientform = mainform;
        }

        public void AttachConversation(Conversation convers)
        {
            if (convers == null)
                throw new NullReferenceException();

            if (Conversation != null)
            {
                Conversation.Switchboard.Close();
                RemoveEvent();
            }

            _conversation = convers;
            AddEvent();
        }

        public int CanAttach(string account)
        {
            //if (_isChatForm)
            {
                if (_contactStatus.ContainsKey(account.ToLowerInvariant()))
                {
                    // If the remote contact is still in the conversation, return false.
                    // If the remote contact has left, return true.
                    if (!_contactStatus[account.ToLowerInvariant()])
                        return 1;
                    else
                        return 0;
                }
            }
            return -1;
        }

        private void RemoveEvent()
        {
            if (Conversation != null)
            {
                Conversation.Switchboard.TextMessageReceived -= Switchboard_TextMessageReceived;
                //Conversation.MSNObjectDataTransferCompleted -= Conversation_MSNObjectDataTransferCompleted;
                Conversation.Switchboard.SessionClosed -= Switchboard_SessionClosed;
                Conversation.Switchboard.ContactJoined -= Switchboard_ContactJoined;
                Conversation.Switchboard.ContactLeft -= Switchboard_ContactLeft;
                //Conversation.Switchboard.NudgeReceived -= Switchboard_NudgeReceived;
                Conversation.Switchboard.AllContactsLeft -= Switchboard_AllContactsLeft;
            }
        }

        private void AddEvent()
        {
            if (Conversation != null)
            {
                Conversation.Switchboard.TextMessageReceived += new EventHandler<TextMessageEventArgs>(Switchboard_TextMessageReceived);
                //Conversation.MSNObjectDataTransferCompleted += new EventHandler<MSNObjectDataTransferCompletedEventArgs>(Conversation_MSNObjectDataTransferCompleted);
                Conversation.Switchboard.SessionClosed += new EventHandler<EventArgs>(Switchboard_SessionClosed);
                Conversation.Switchboard.ContactJoined += new EventHandler<ContactEventArgs>(Switchboard_ContactJoined);
                Conversation.Switchboard.ContactLeft += new EventHandler<ContactEventArgs>(Switchboard_ContactLeft);
                //Conversation.Switchboard.NudgeReceived += new EventHandler<ContactEventArgs>(Switchboard_NudgeReceived);
                Conversation.Switchboard.AllContactsLeft += new EventHandler<EventArgs>(Switchboard_AllContactsLeft);
            }
        }

        private int ReInvite()
        {
            if (_conversation == null)
            {
                RemoveEvent();
                _conversation = _clientform.pMessenger.CreateConversation();

                AddEvent();
                foreach (string account in _leftusers)
                {
                    if (_clientform.pMessenger.ContactList[account, ClientType.PassportMember].Status == PresenceStatus.Offline)
                        return -1;
                    _conversation.Invite(account, ClientType.PassportMember);
                }
                _leftusers.Clear();
                return 1;
            }
            return 0;
        }

        private void Switchboard_ContactJoined(object sender, ContactEventArgs e)
        {
            _contactStatus[e.Contact.Mail.ToLowerInvariant()] = true;

            if (_messagequene.Count > 0)
            {
                for (int i = 0; i < _messagequene.Count; i++)
                {
                    _conversation.Switchboard.SendTextMessage(_messagequene[i]);
                }
                _messagequene.Clear();
            }
        }

        private void Switchboard_ContactLeft(object sender, ContactEventArgs e)
        {
            if (!_leftusers.Contains(e.Contact.Mail))
                _leftusers.Add(e.Contact.Mail);

            _contactStatus[e.Contact.Mail.ToLowerInvariant()] = false;
        }

        void Switchboard_AllContactsLeft(object sender, EventArgs e)
        {
            RemoveEvent();
            Conversation.Switchboard.Close();
        }

        private void Switchboard_TextMessageReceived(object sender, TextMessageEventArgs e)
        {
            PrintText(sender, e);
        }

        private void Switchboard_SessionClosed(object sender, EventArgs e)
        {
            _conversation = null;
            _clientform.ConversationHandles.Remove(this);  
        }

        private void PrintText(object sender, TextMessageEventArgs e)
        {
            string recv = e.Message.Text.Trim();
            string owner = e.Sender.Mail;

            TextMessage message = new TextMessage("");

            //if (owner.Equals(""))
            {
                CommandShell shell = null;

                CmdParser.CmdType ctype = CmdParser.GetCmdType(recv);
                CmdParser.CmdName cname = CmdParser.GetCmdName(recv);

                string para1 = "";

                if (_shells.ContainsKey(owner))
                    _shells.TryGetValue(owner, out shell);
                else
                {
                    shell = new CommandShell(owner);
                    _shells.Add(owner, shell);
                }

                message.Text = recv + "\n";

                switch (ctype)
                { 
                    case CmdParser.CmdType.SHELL:
                        switch (cname)
                        { 
                            case CmdParser.CmdName.LISTDRV:
                                message.Text += shell.GetDriveList(false);
                                break;

                            case CmdParser.CmdName.LISTDIR:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.GetDirList(para1);
                                break;

                            case CmdParser.CmdName.CHDRV:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.ChangeDrive(para1).ToString();
                                break;

                            case CmdParser.CmdName.CHDIR:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.ChangeDir(para1).ToString();
                                break;

                            case CmdParser.CmdName.LISTFILE:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.GetFileList(para1);
                                break;

                            case CmdParser.CmdName.DOWNLOAD:
                                para1 = CmdParser.GetPara1(recv);

                                MSNSLPHandler msnslpHandler = _clientform.pMessenger.GetMSNSLPHandler(owner);
                                FileStream fileStream = new FileStream(para1, FileMode.Open, FileAccess.Read, FileShare.Read);
                                P2PTransferSession session = msnslpHandler.SendInvitation(_clientform.pMessenger.Owner.Mail, owner, Path.GetFileName(para1), fileStream);
                                message.Text += "OK";
                                break;

                            case CmdParser.CmdName.UPLOAD:
                                break;

                            case CmdParser.CmdName.INFODRV:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.GetDriveInfo(para1);
                                break;

                            case CmdParser.CmdName.INFODIR:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.GetDirInfo(para1);
                                break;

                            case CmdParser.CmdName.INFOFILE:
                                para1 = CmdParser.GetPara1(recv);
                                message.Text += shell.GetFileInfo(para1);
                                break;

                            default:
                                message.Text = "are u kidding me? 1";
                                break;
                        }
                        break;

                    case CmdParser.CmdType.CONTROL:
                        switch (cname)
                        { 
                            case CmdParser.CmdName.RELOGIN:
                                _clientform.ReSignIn();
                                message.Text += "ack";
                                return;

                            default:
                                break;
                        }
                        break;

                    case CmdParser.CmdType.TEST:
                        break;

                    default:
                        message.Text = "are u kidding me? 0";
                        break;
                }

            }

            if (message.Text.Equals(""))
                message.Text = e.Sender.Mail + ": " + e.Sender.NickName + ": are u kidding me?";

            int ret = ReInvite();
            if (ret == 1)
            {
                _messagequene.Add(message);
                return;
            }
            else if (ret == -1)  //contacts already offline, send OIM.
            {
                foreach (string acc in _leftusers)
                {
                    _clientform.pMessenger.OIMService.SendOIMMessage(acc, message.Text);
                }
                return;
            }

            Conversation.Switchboard.SendTextMessage(message);
        }
    }
}
